package person.wend.javalearnexample.util.concurrent.executor;

import java.util.concurrent.*;

public class ExecutorsExample {
    public static void main(String[] args) {
        createExecutorService();
        createScheduledExecutorService();
        usedDefaultThreadFactory();
    }

    public static void usedDefaultThreadFactory() {
        // 创建一个Executors.defaultThreadFactory
        ThreadFactory customThreadFactory = Executors.defaultThreadFactory();

        // 使用自定义的 ThreadFactory 创建一个 ExecutorService
        ExecutorService executorService = Executors.newCachedThreadPool(customThreadFactory);

        // 提交任务到线程池执行
        for (int i = 0; i < 10; i++) {
            executorService.submit(() -> {
                System.out.println(Thread.currentThread().getName() + " is running.");
            });
        }

        // 关闭线程池
        executorService.shutdown();
    }

    public static void createScheduledExecutorService() {
        ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
        // 提交一个延迟2秒后执行的任务
        executor.schedule(() -> System.out.println("任务执行了"), 2, TimeUnit.SECONDS);
        // 关闭执行器
        executor.shutdown();

        ScheduledExecutorService executor2 = Executors.newScheduledThreadPool(3);
        // 提交一个延迟2秒后执行的任务
        executor2.schedule(() -> System.out.println("任务执行了"), 2, TimeUnit.SECONDS);
        executor2.shutdown();
    }


    public static void createExecutorService() {
        // 创建一个可缓存线程池，如果线程空闲60秒后将会被回收
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        // 创建一个固定大小的线程池
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        // 创建一个单线程化的线程池
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        // 创建一个支持定时及周期性任务执行的线程池
        ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        // 创建一个json-task 工作窃取线程池
        ExecutorService workStealingPool = Executors.newWorkStealingPool();

        // 使用cachedThreadPool执行任务
        for (int i = 0; i < 10; i++) {
            cachedThreadPool.execute(new RunnableTask("CachedThreadPool Task " + i));
        }

        // 使用fixedThreadPool执行任务
        for (int i = 0; i < 5; i++) {
            fixedThreadPool.execute(new RunnableTask("FixedThreadPool Task " + i));
        }

        // 使用singleThreadExecutor执行任务
        for (int i = 0; i < 3; i++) {
            singleThreadExecutor.execute(new RunnableTask("SingleThreadExecutor Task " + i));
        }

        // 使用scheduledThreadPool执行定时任务
        for (int i = 0; i < 3; i++) {
            // 延迟1秒后执行任务
            scheduledThreadPool.execute(new RunnableTask("ScheduledThreadPool Task " + i));
        }

        // 使用 workStealingPool 执行任务
        for (int i = 0; i < 5; i++) {
            workStealingPool.execute(new RunnableTask("WorkStealingPool Task " + i));
        }

        // 关闭所有线程池
        shutdownAndAwaitTermination(cachedThreadPool);
        shutdownAndAwaitTermination(fixedThreadPool);
        shutdownAndAwaitTermination(singleThreadExecutor);
        shutdownAndAwaitTermination(scheduledThreadPool);
        shutdownAndAwaitTermination(workStealingPool);
    }

    // 一个简单的Runnable任务
    static class RunnableTask implements Runnable {
        private final String taskName;

        RunnableTask(String taskName) {
            this.taskName = taskName;
        }

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " is executing " + taskName);
            try {
                // 模拟任务执行时间
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    // 安全关闭线程池的方法
    static void shutdownAndAwaitTermination(ExecutorService pool) {
        pool.shutdown(); // 禁止提交新任务
        try {
            // 等待现有任务终止
            if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
                pool.shutdownNow(); // 取消当前执行的任务
                // 等待任务响应被取消
                if (!pool.awaitTermination(60, TimeUnit.SECONDS))
                    System.err.println("线程池未正常终止");
            }
        } catch (InterruptedException ie) {
            // 重新取消当前线程进行中断
            pool.shutdownNow();
            // 保留中断状态
            Thread.currentThread().interrupt();
        }
    }
}
